home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJLSR111.ZIP / lib / mcount.c < prev   
C/C++ Source or Header  |  1992-07-06  |  3KB  |  142 lines

  1. #include <fcntl.h>
  2.  
  3. /* header of a GPROF type file
  4. */
  5. typedef struct {
  6.   long low;
  7.   long high;
  8.   long nbytes;
  9. } header;
  10.  
  11. /* entry of a GPROF type file
  12. */
  13. typedef struct {
  14.     unsigned long from;
  15.     unsigned long to;
  16.     unsigned long count;
  17. } MTABE;
  18.  
  19. /* internal form - sizeof(MTAB) is 4096 for efficiency
  20. */
  21. typedef struct MTAB {
  22.   MTABE calls[341];
  23.   struct MTAB *prev;
  24. } MTAB;
  25.  
  26. static header h;
  27. short *histogram asm("mcount_histogram");
  28. short mcount_skip asm("mcount_skip");
  29. static int histlen;
  30. static MTAB *mtab=0;
  31.  
  32. /* called by functions.  Use the pointer it provides to cache
  33. ** the last used MTABE, so that repeated calls to/from the same
  34. ** pair works quickly - no lookup.
  35. */
  36. void mcount(_to)
  37. {
  38.   MTAB *m;
  39.   int i;
  40.   int to;
  41.   int ebp;
  42.   int from;
  43.   int mtabi;
  44.   MTABE **cache;
  45.  
  46.   mcount_skip = 1;
  47.   asm("movl %%edx,%0" : "=g" (cache)); /* obtain the cached pointer */
  48.   to = *((&_to)-1) - 12;
  49.   ebp = *((&_to)-2); /* glean the caller's return address from the stack */
  50.   from = ((int *)ebp)[1];
  51.   if (*cache && ((*cache)->from == from) && ((*cache)->to == to))
  52.   {
  53.     /* cache paid off - works quickly */
  54.     (*cache)->count++;
  55.     mcount_skip = 0;
  56.     return;
  57.   }
  58.  
  59.   /* no cache hit - search all mtab tables for a match, or an empty slot */
  60.   mtabi = -1;
  61.   for (m=mtab; m; m=m->prev)
  62.   {
  63.     for (i=0; i<341; i++)
  64.     {
  65.       if (m->calls[i].from == 0)
  66.       {
  67.         /* empty slot - end of table */
  68.         mtabi = i;
  69.         break;
  70.       }
  71.       if ((m->calls[i].from == from) &&
  72.           (m->calls[i].to == to))
  73.         {
  74.           /* found a match - bump count and return */
  75.           m->calls[i].count ++;
  76.           *cache = m->calls + i;
  77.           mcount_skip = 0;
  78.           return;
  79.         }
  80.     }
  81.   }
  82.   if (mtabi != -1)
  83.   {
  84.     /* found an empty - fill it in */
  85.     mtab->calls[mtabi].from = from;
  86.     mtab->calls[mtabi].to = to;
  87.     mtab->calls[mtabi].count = 1;
  88.     *cache = mtab->calls + mtabi;
  89.     mcount_skip = 0;
  90.     return;
  91.   }
  92.   /* lob off another page of memory and initialize the new table */
  93.   m = (MTAB *)sbrk(sizeof(MTAB));
  94.   memset(m, 0, sizeof(MTAB));
  95.   m->prev = mtab;
  96.   mtab = m;
  97.   m->calls[0].from = from;
  98.   m->calls[0].to = to;
  99.   m->calls[0].count = 1;
  100.   *cache = m->calls;
  101.   mcount_skip = 0;
  102. }
  103.  
  104. extern int etext;
  105.  
  106. extern void mcount_isr_init() asm("mcount_isr_init");
  107. extern void mcount_init() asm("mcount_init");
  108. void mcount_init()
  109. {
  110.   /* this is called by gcrt0.s, before the program starts */
  111.   int hs;
  112.   h.low = 0x1020;
  113.   h.high = (int)&etext;
  114.   histlen = (h.high-h.low)/4*sizeof(short);
  115.   h.nbytes = sizeof(header) + histlen;
  116.   histogram = (short *)sbrk(histlen);
  117.   memset(histogram, 0, histlen);
  118.  
  119.   /* here, do whatever it takes to initialize the timer interrupt */
  120.   mcount_isr_init();
  121. }
  122.  
  123. extern void mcount_write() asm("mcount_write");
  124. void mcount_write()
  125. {
  126.   /* this is called by gcrt0.s, after the program exits. */
  127.   MTAB *m;
  128.   int i, f;
  129.  
  130.   f = open("gmon.out", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
  131.   write(f, &h, sizeof(header));
  132.   write(f, histogram, histlen);
  133.   for (m=mtab; m; m=m->prev)
  134.   {
  135.     for (i=0; i<341; i++)
  136.       if (m->calls[i].from == 0)
  137.         break;
  138.     write(f, m->calls, i*12);
  139.   }
  140.   close(f);
  141. }
  142.